package com.jt.www.common.service.impl;

import com.jt.www.common.service.MonitorErrorService;
import com.jt.www.common.service.SendEmailsService;
import com.jt.www.dao.mapper.endorse.SaveEndorseParamMapper;
import com.jt.www.dao.mapper.issue.mapper.IssuePolicyLogEntityMapper;
import com.jt.www.domain.enums.pc.IssuePolicyLogTypeEnum;
import com.jt.www.domain.vo.MonitorErrorVO;
import com.jt.www.enums.issue.AppStatusEnum;
import com.jt.www.enums.issue.IssueEnum;
import com.jt.www.enums.issue.PolicyInterfaceEnum;
import com.jt.www.enums.issue.PolicyOrinvoiceSendStatusEnum;
import com.jt.www.model.issue.entity.IssuePolicyLogEntity;
import com.jt.www.model.param.endorse.AppDetailProParam;
import com.jt.www.model.param.endorse.SaveEndorseParam;
import com.jt.www.model.reps.GenericDataResponse;
import com.jt.www.model.reps.ResponseData;
import com.jt.www.model.vo.endorse.AppDetailProVo;
import com.jt.www.remote.ins.InsClient;
import com.jt.www.util.DateUtils;
import com.jt.www.util.RedisUtil;
import org.assertj.core.util.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.weekend.Weekend;
import tk.mybatis.mapper.weekend.WeekendCriteria;

import java.util.List;

/**
 * 异常监控
 * Created by shaoyn on 2020/06/29.
 */
@Service
public class MonitorErrorServiceImpl implements MonitorErrorService {

    public static final Logger log = LoggerFactory.getLogger(MonitorErrorServiceImpl.class);
    private static final String MESSAGE_LOCK_KEY = "EDU_MONITOR_ERROR";
    /**
     * 单个服务器出单查询缓存失效时间 因不同的定时任务决定
     */
    private static final long MONITOR_ERROR_TIME_OUT = 100L;
    @Autowired
    private IssuePolicyLogEntityMapper issuePolicyLogEntityMapper;
    @Autowired
    private InsClient insClient;
    @Autowired
    private SaveEndorseParamMapper saveEndorseParamMapper;
    @Autowired
    private SendEmailsService sendEmailsService;

    @Override
    public void process() {
        //保证所有服务器 只执行一次
        if (RedisUtil.setLock(MESSAGE_LOCK_KEY, "1", MONITOR_ERROR_TIME_OUT)) {
            //出单失败
            List<MonitorErrorVO> issueErrorList = getIssueError();
            //电子保单，电子发票处理失败
            List<MonitorErrorVO> ePolicyError = getEPolicyError();
            sendEmailsService.monitorError(issueErrorList, ePolicyError);
        }
    }

    /**
     * 电子保单，电子发票处理失败
     *
     * @return
     */
    private List<MonitorErrorVO> getEPolicyError() {
        String aWeekAgo = DateUtils.getlastWeakTime(DateUtils.DATE_FORMAT_YYYY_MM_DD);
        List<MonitorErrorVO> monitorErrors = Lists.newArrayList();
        Weekend<IssuePolicyLogEntity> weekend = Weekend.of(IssuePolicyLogEntity.class);
        WeekendCriteria<IssuePolicyLogEntity, Object> criteria = weekend.weekendCriteria();
//        criteria.andEqualTo(IssuePolicyLogEntity::getType, "1");
        //1未处理 2处理成功  不做处理
        criteria.andNotIn(IssuePolicyLogEntity::getStatus, Lists.newArrayList(PolicyOrinvoiceSendStatusEnum.PISS_01.getCode(),
                PolicyOrinvoiceSendStatusEnum.PISS_02.getCode(), PolicyOrinvoiceSendStatusEnum.PISS_08.getCode()));
        criteria.andGreaterThan(IssuePolicyLogEntity::getCreateTime, aWeekAgo);
        criteria.andNotEqualTo(IssuePolicyLogEntity::getIfCode, PolicyInterfaceEnum.CODE_24.getIfCode());
        List<IssuePolicyLogEntity> issuePolicyLogEntityList = issuePolicyLogEntityMapper.selectByExample(weekend);
        for (IssuePolicyLogEntity issuePolicyLogEntity : issuePolicyLogEntityList) {
            MonitorErrorVO monitorError = new MonitorErrorVO();
            monitorError.setAppCode(issuePolicyLogEntity.getApplicationFormCode());
            monitorError.setProName(IssueEnum.getProNameByProCode(issuePolicyLogEntity.getProCode()));
            monitorError.setDesc(IssuePolicyLogTypeEnum.getDescByType(issuePolicyLogEntity.getType()));
            monitorError.setErrorMsg(PolicyOrinvoiceSendStatusEnum.getEnumByCode(issuePolicyLogEntity.getStatus()).getDesc());
            monitorErrors.add(monitorError);
        }

        return monitorErrors;
    }

    /**
     * 出单失败
     *
     * @return
     */
    private List<MonitorErrorVO> getIssueError() {
        List<MonitorErrorVO> monitorErrors = Lists.newArrayList();

        Weekend<SaveEndorseParam> weekend = new Weekend<>(SaveEndorseParam.class);
        WeekendCriteria<SaveEndorseParam, Object> criteria = weekend.weekendCriteria();
        //只判断投保单的 因为批单暂时没有线上出单
        criteria.andEqualTo(SaveEndorseParam::getIsIns, 1);
        criteria.andEqualTo(SaveEndorseParam::getIsDeleted, false);
        List<SaveEndorseParam> saveEndorseParams = saveEndorseParamMapper.selectByExample(weekend);
        for (SaveEndorseParam saveEndorseParam : saveEndorseParams) {
            AppDetailProParam p = new AppDetailProParam();
            AppDetailProVo detailVos = null;
            ResponseEntity<GenericDataResponse<AppDetailProVo>> appDetailPro;
            p.setAppCode(saveEndorseParam.getInsuranceId());
            p.setChannelCode("edu");    // 渠道编号
            p.setUserCode(saveEndorseParam.getUsercode());
            try {
                appDetailPro = insClient.searchAppDetailPro(p);
                detailVos = appDetailPro.getBody().getData();
            } catch (Exception e) {
                log.error("查询投保单信息失败{}", saveEndorseParam.getInsuranceId());

            }
            if (detailVos != null) {
                if (AppStatusEnum.AS_09.getCode().equals(detailVos.getApplicationStatus()) || AppStatusEnum.AS_22.getCode().equals(detailVos.getApplicationStatus())) {
                    try {
                        ResponseData responseData = insClient.tourIssueFail(saveEndorseParam.getInsuranceId());
                        if ("0000".equals(responseData.getCode()) && "成功".equals(responseData.getMsg())) {
                            MonitorErrorVO monitorError = new MonitorErrorVO();
                            monitorError.setAppCode(saveEndorseParam.getInsuranceId());
                            monitorError.setDesc("出单失败");
                            monitorError.setProName(detailVos.getProductName());
                            if (null != responseData.getData()) {
                                monitorError.setErrorMsg(responseData.getData().toString());
                            }
                            monitorErrors.add(monitorError);
                        }
                    } catch (Exception e) {
                        log.error("查询出单失败信息异常{}", saveEndorseParam.getInsuranceId(), e);
                    }
                }
            }
        }
        return monitorErrors;
    }


}
